package cc.tuhaolicai.mt.user.mobile.tool;

import com.jfinal.kit.PropKit;
import org.asyou.mongo.Count;
import org.asyou.mongo.FindMany;
import org.asyou.mongo.Page;
import org.asyou.mongo.Update;
import org.asyou.mongo.dao.IMongoAdapter;
import org.asyou.mongo.dao.MongoAdapter;
import org.asyou.mongo.wrapper.DateFromTo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.tools.data.text.ToolJson;
import pro.tools.data.text.ToolStr;

import java.util.List;
import java.util.Map;

/**
 * mongo的工具类
 *
 * @author SeanDragon
 *         Create By 2017-05-02 10:35
 */
public class ToolMongo {

    private static final Logger LOG = LoggerFactory.getLogger(ToolMongo.class);

    public static <T> T insertOne(T data) {
        try {
            if (Factory.getAdapter().insertOne(data) == 0L) {
                return data;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return null;
    }

    public static <T> List<T> insertMany(List<T> dataList) {
        try {
            if (Factory.getAdapter().insertMany(dataList) == 0L) {
                return dataList;
            }
            ;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return null;
    }

    public static <T> boolean deleteOne(T data) {
        try {
            return Factory.getAdapter().deleteOne(data) > 0L;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private static <T> boolean deleteMany(T data) {
        try {
            return Factory.getAdapter().deleteMany(data) > 0L;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static <T> boolean updateOne(T queue, T data) {
        try {
            Update.Result result = Factory.getAdapter().updateOne(queue, data);
            return result.getModifiedCount() > 0L;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static <T> boolean updateMany(T queue, T data) {
        try {
            Update.Result result = Factory.getAdapter().updateMany(queue, data);
            return result.getModifiedCount() > 0L;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    //region find

    //region common
    public static <T> T findOne(T t) {
        return Factory.getAdapter().findOne(t);
    }

    public static <T> List<T> findMany(T t) {
        return findMany(t, new PageInfo(), false, false);
    }

    public static <T> List<T> findMany(T t, PageInfo pageInfo) {
        return findMany(t, pageInfo, false, false);
    }

    public static <T> List<T> findMany(T t, boolean contain, boolean or) {
        return findMany(t, new PageInfo(), contain, or);
    }

    public static <T> List<T> findMany(T t, PageInfo pageInfo, boolean contain, boolean or) {
        return findPage(t, pageInfo, contain, or).getList();
    }
    //endregion

    //region not
    public static <T> List<T> findMany(T t, boolean not) {
        return findMany(t, new PageInfo(), false, false, not);
    }

    public static <T> List<T> findMany(T t, PageInfo pageInfo, boolean not) {
        return findMany(t, pageInfo, false, false, not);
    }

    public static <T> List<T> findMany(T t, boolean contain, boolean or, boolean not) {
        return findMany(t, new PageInfo(), contain, or, not);
    }

    public static <T> List<T> findMany(T t, PageInfo pageInfo, boolean contain, boolean or, boolean not) {
        return findPage(t, pageInfo, contain, or, not).getList();
    }
    //endregion

    //region common
    public static <T> Page<T> findPage(T t) {
        return findPage(t, new PageInfo(), false, false);
    }

    public static <T> Page<T> findPage(T t, PageInfo pageInfo) {
        return findPage(t, pageInfo, false, false);
    }

    public static <T> Page<T> findPage(T t, PageInfo pageInfo, boolean contain, boolean or) {
        Map<String, Integer> sortMap = pageInfo.getSortMap();
        String sortStr = ToolJson.mapToJson(sortMap);

        FindMany findMany = find(t, pageInfo.getDateFromTo(), contain, or);
        if (!ToolStr.isBlank(sortStr)) {findMany = findMany.sort(sortStr);}

        return findMany.page(pageInfo.getPageIndex(), pageInfo.getPageSize());
    }
    //endregion

    //region not
    public static <T> Page<T> findPage(T t, boolean not) {
        return findPage(t, new PageInfo(), false, false, not);
    }

    public static <T> Page<T> findPage(T t, PageInfo pageInfo, boolean not) {
        return findPage(t, pageInfo, false, false, not);
    }

    public static <T> Page<T> findPage(T t, PageInfo pageInfo, boolean contain, boolean or, boolean not) {

        Map<String, Integer> sortMap = pageInfo.getSortMap();
        String sortStr = ToolJson.mapToJson(sortMap);

        FindMany findMany = find(t, pageInfo.getDateFromTo(), contain, or, not);
        if (!ToolStr.isBlank(sortStr)) {findMany = findMany.sort(sortStr);}

        return findMany.page(pageInfo.getPageIndex(), pageInfo.getPageSize());
    }
    //endregion

    //region common
    public static <T> long count(T t) {
        return count(t, new DateFromTo());
    }

    public static <T> long count(T t, DateFromTo dateFromTo) {
        return count(t, dateFromTo, false, false);
    }

    public static <T> long count(T t, boolean contain, boolean or) {
        return count(t, new DateFromTo(), contain, or);
    }

    public static <T> long count(T t, DateFromTo dateFromTo, boolean contain, boolean or) {
        return count(t, dateFromTo, contain, or, false);
    }
    //endregion

    //region not
    public static <T> long count(T t, boolean not) {
        return count(t, new DateFromTo(), not);
    }

    public static <T> long count(T t, DateFromTo dateFromTo, boolean not) {
        return count(t, dateFromTo, false, false, not);
    }
    //endregion

    //region 基础方法
    public static <T> long count(T t, boolean contain, boolean or, boolean not) {
        return count(t, new DateFromTo(), contain, or, not);
    }

    public static <T> long count(T t, DateFromTo dateFromTo, boolean contain, boolean or, boolean not) {
        Count count = Factory.getAdapter().count(t);
        if (dateFromTo != null) {count = count.dateFromTo(dateFromTo);}
        if (contain) {count = count.contain();}
        if (or) {count = count.OR();}
        if (not) {count = count.NOT();}
        return count.count();
    }

    public static <T> FindMany find(T t, DateFromTo dateFromTo, boolean contain, boolean or) {
        return find(t, dateFromTo, contain, or, false);
    }

    public static <T> FindMany find(T t, DateFromTo dateFromTo, boolean contain, boolean or, boolean not) {
        FindMany findMany = Factory.getAdapter().findMany(t);
        if (dateFromTo != null) {findMany = findMany.dateFromTo(dateFromTo);}
        if (contain) {findMany = findMany.contain();}
        if (or) {findMany = findMany.OR();}
        if (not) {findMany = findMany.NOT();}
        return findMany;
    }
    //endregion

    //endregion

    public static class Factory {
        static IMongoAdapter getAdapter() {
            try {
                return new MongoAdapter(PropKit.get("config.mongo.id"));
            } catch (Exception e) {
                e.printStackTrace();
                String message = "初始化Mongo插件失败！";
                LOG.warn(message);
                throw new RuntimeException(message);
            }
        }
    }
}
